/****************************************************************************
*
* Description: Basic file implementation
* Module: 'basic_file.h'
* Created at: 24.06.06 17:02:38 UTC
*
* $Revision$
*
****************************************************************************/
#pragma once

#if !defined(__STORAGE_BASIC_FILE_H__)
#define __STORAGE_BASIC_FILE_H__

#include <fstream>
#include <iterator>
#include <common/memory_manager.h>
#include <storage/storage.h>
#include <storage/source.h>
#include <storage/sink.h>

namespace storage {

/* Basic file. Raw data in one segment.  */
struct basic_file :
	public storage_t,
	public source,
	public sink
{
	/* Default ctor. Anonymous storage.  */
    basic_file()
    {}

	/* Ctor. File name specified.  */
    basic_file(std::string & name):
    	name_(name)
    {
    }

	/* Ctor. Anonymous with specified size.  */
    basic_file(bytes_t & data):
        data_(data)
    {}

	/* Ctor. Full specification.  */
    basic_file(std::string & name, bytes_t & data):
        name_(name),
        data_(data)
    {}

	/* Copy ctor.  */
    basic_file(const basic_file & o):
        name_(o.name_),
        data_(o.data_)
    {}

	/* Dtor.  */
	virtual ~basic_file()
	{}

	/* -------- storage_t interface ----------  */
	virtual std::string& name()
	{
		return name_;
	}

	virtual bytes_t& data()
	{
		return data_;
	}
	/* ------ storage_t interface end --------  */

	/* --------- source_t interface ----------  */
	/* Read data from the specified file.  */
    virtual void read()
    {
		/* TODO: Should be replaced with binary reader.  */
        using namespace std;
        ifstream                        i_str(name().c_str(), ios::in | ios::binary);
        char_traits<uint8>::int_type	i_bin;
        back_insert_iterator<bytes_t>   o_bin(data());

        for( i_bin = i_str.get(); !i_str.fail(); i_bin = i_str.get() )
            o_bin = char_traits<uint8>::to_char_type(i_bin);

        i_str.close();
    };

	/* Check that data is valid for this source.  */
    virtual bool is_valid()
    {
    	return true;
    }

protected:
	/* Helper class for map_to routine.
	 * Make conversion for data while copy process.	 */
	template< class T >
	class data_puller
	{
	public:
		data_puller(common::memory::memory_manager_t::region_t & region):
			inserter_(region.block())
		{}

		void operator()(T & val)
		{
			inserter_ = static_cast<common::memory::memory_manager_t::region_t::item_t>(val);
		}

	private:
		std::back_insert_iterator<common::memory::memory_manager_t::region_t::container_t> inserter_;
	};

public:
	/* Routine maps provided file to memory.  */
	virtual void map_to(common::memory::memory_manager_t & mgr)
	{
		common::memory::memory_manager_t::region_t & block = mgr.create_block(0, 0);
		std::for_each(data().begin(), data().end(), data_puller<storage_t::container_t::value_type>(block));
	}

	/* Return list of file entry points.  */
	virtual void get_entry_points(addrs_t & eps)
	{
		/* We consider 0 as enrty point for arbitrary binary.  */
		eps.push_back(0);
	}
	/* ------- source_t interface end --------  */

	/* ---------- sink_t interface -----------  */
	/* Write data to specified file.  */
    virtual void write()
    {
        using namespace std;
        ofstream    o_str(name().c_str(), ios::out | ios::binary);
        o_str.write(reinterpret_cast<char *>(&data()[0]), data().size());
        o_str.close();
    }
	/* -------- sink_t interface end ---------  */

protected:
	std::string name_;
	bytes_t		data_;
};

} /* End of storage.  */

#endif  /* End of __STORAGE_BASIC_FILE_H__.  */
